﻿using FreeScheduler;
using Gengens.Disk.WebApi.util;
using Serilog;
using System.Reflection;
using System.Linq;

namespace Gengens.Disk.WebApi
{
    /// <summary>
    /// 元数据
    /// </summary>
    public static class MateData
    {
        #region 容器

        public static IServiceProvider serviceProvider;
        public static ConfigurationManager configuration;

        #endregion

        #region 配置常量

        public static string LoginKey 
        {
            get
            {
                if (configuration == default) {
                    Log.Error("MateData中的Configuration未初始化，LoginKey获取失败");
                    return string.Empty;
                }

                return configuration["Login:Key"];
            }
        }

        #endregion

        #region Mate变量

        private static string _baseUrl;
        public static string BaseUrl { 
            get
            {
                _baseUrl ??= AppDomain.CurrentDomain.BaseDirectory;
                return _baseUrl;
            }
        }

        private static List<Type> _allTypes;

        public static List<Type> AllType {
            get
            {
                if(_allTypes != default) return _allTypes;

                var assems = AppDomain.CurrentDomain.GetAssemblies();
                var allRefAssems = assems.SelectMany(asse => asse.GetReferencedAssemblies()).Select(a => Assembly.Load(a));
                var assemsTyps = assems.SelectMany(asse => asse.GetTypes()).ToList();
                var refAssemsTypes = allRefAssems.SelectMany(asse => asse.GetTypes()).ToList();
                _allTypes = assemsTyps.Union(refAssemsTypes).ToList();
                return _allTypes;   
            }
            set => _allTypes = value;
        }

        private static List<Assembly> _allAssemblies;
        public static List<Assembly> AllAssemblies
        {
            get {
                if (_allAssemblies != default) return _allAssemblies;
                var a1 = AppDomain.CurrentDomain.GetAssemblies().ToList();
                var a2 = a1.SelectMany(a => a.GetReferencedAssemblies()).Select(a => Assembly.Load(a)).ToList();
                return a1.Union(a2).ToList();
            }
        }

        private static List<FileInfo> _allDllFile;
        public static List<FileInfo> AllDllFile { 
            get
            {
                if (_allDllFile != default) return _allDllFile;

                DirectoryInfo baseDir = new DirectoryInfo(BaseUrl);
                List<FileInfo> dlls = new List<FileInfo>();
                FileUtils.Recursion(baseDir,_ => { }, f => {
                    if (f.Extension.Equals(".dll", StringComparison.OrdinalIgnoreCase)) {
                        dlls.Add(f);
                    }
                });

                _allDllFile = dlls;
                return _allDllFile;
            }
        }
        
        private static List<Assembly> _entityAssemblys;
        public static List<Assembly> EntityAssemblys { 
            get
            {
                _entityAssemblys ??= AllAssemblies.FindAll(a => a.FullName.Contains("gengens.disk.entity", StringComparison.OrdinalIgnoreCase));
                return _entityAssemblys;
            }
        }

        private static List<Assembly> _repositoryAssmblys;
        public static List<Assembly> RepositoryAssmblys { 
            get
            {
                _repositoryAssmblys ??= AllAssemblies.FindAll(a => a.FullName.Contains("gengens.disk.repository", StringComparison.OrdinalIgnoreCase));
                return _repositoryAssmblys;
            }
        }

        private static List<Assembly> _serviceAssmblys;
        public static List<Assembly> ServiceAssmblys
        {
            get
            {
                _serviceAssmblys ??= AllAssemblies.FindAll(a => a.FullName.Contains("gengens.disk.service", StringComparison.OrdinalIgnoreCase));
                return _serviceAssmblys;
            }
        }

        #endregion

        #region 定时任务

        public static event Action<TaskInfo> SchedulerTaskEvent;
        private static void OnSchedulerTask(TaskInfo task) => SchedulerTaskEvent?.Invoke(task);

        public static Scheduler _scheduler;
        public static Scheduler Scheduler 
        { 
            get 
            {
                if (_scheduler != default) return _scheduler;
                _scheduler = new FreeSchedulerBuilder().OnExecuting(
                    task => {
                        Log.Information("[任务执行] - " + task.Topic, task);
                        OnSchedulerTask(task);
                    }).Build();

                SchedulerLauncher.Init();

                return _scheduler;
            }
            set => value = _scheduler; 
        }



        /// <summary>
        /// 定时任务
        /// </summary>
        public static void TimingTask()
        {
            Scheduler scheduler = new FreeSchedulerBuilder()
                .OnExecuting(task => 
                {
                    Log.Information("执行", task);
                }
                )
                .Build(); 
        }

        #endregion

        #region 废弃

        /**
         *  private static List<Assembly> _entityAssemblys;
                public static List<Assembly> EntityAssemblys { 
                    get
                    {
                        if (_entityAssemblys != default) return _entityAssemblys;
                        List<FileInfo> entityDllFiles = AllDllFile.FindAll(f => f.FullName.Contains("gengens.disk.entity",StringComparison.OrdinalIgnoreCase));
                        _entityAssemblys = entityDllFiles.Select(f => Assembly.LoadFile(f.FullName)).ToList();
                        return _entityAssemblys;
                    }
                }

                private static List<Assembly> _repositoryAssmblys;
                public static List<Assembly> RepositoryAssmblys { 
                    get
                    {
                        if (_repositoryAssmblys != default) return _repositoryAssmblys;
                        List<FileInfo> entityDllFiles = AllDllFile.FindAll(f => f.FullName.Contains("gengens.disk.repository", StringComparison.OrdinalIgnoreCase));
                        _repositoryAssmblys = entityDllFiles.Select(f => Assembly.LoadFile(f.FullName)).ToList();
                        return _repositoryAssmblys;
                    }
                }

                private static List<Assembly> _serviceAssmblys;
                public static List<Assembly> ServiceAssmblys
                {
                    get
                    {
                        if (_serviceAssmblys != default) return _serviceAssmblys;
                        List<FileInfo> entityDllFiles = AllDllFile.FindAll(f => f.FullName.Contains("gengens.disk.service", StringComparison.OrdinalIgnoreCase));
                        _serviceAssmblys = entityDllFiles.Select(f => Assembly.LoadFile(f.FullName)).ToList();
                        return _serviceAssmblys;
                    }
                }
         */

        #endregion

    }
}
